﻿// Copyright 2009 Mike Geise
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

namespace Falcon.Core.Services
{
	using System;
	using Falcon.Core.Collections;
	using Falcon.Core.Domain;
	using Falcon.Core.Domain.Enums;
	using Falcon.Core.Domain.Repositories;
	using Falcon.Core.Domain.Services;
	using Falcon.Core.Domain.Values;
	using Falcon.Core.Extensions;

	public class UserAlbumService : IUserAlbumService
	{
		/// <summary>
		/// Initializes a new instance of the <see cref="UserAlbumService"/> class.
		/// </summary>
		/// <param name="identityService">The identity service.</param>
		/// <param name="userContactService">The user contact service.</param>
		/// <param name="userAlbumRepository">The user album repository.</param>
		public UserAlbumService(
			IIdentityService identityService,
			IUserContactService userContactService, 
			IUserAlbumRepository userAlbumRepository)
		{
			this.IdentityService = identityService;
			this.UserContactService = userContactService;
			this.UserAlbumRepository = userAlbumRepository;
		}

		/// <summary>
		/// Gets or sets the identity service.
		/// </summary>
		/// <value>The identity service.</value>
		public IIdentityService IdentityService
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets or sets the user contact service.
		/// </summary>
		/// <value>The user contact service.</value>
		public IUserContactService UserContactService
		{
			get; 
			private set;
		}

		/// <summary>
		/// Gets or sets the user album repository.
		/// </summary>
		/// <value>The user album repository.</value>
		public IUserAlbumRepository UserAlbumRepository
		{
			get; 
			private set;
		}

		/// <summary>
		/// Gets the user album by id.
		/// </summary>
		/// <param name="id">The id.</param>
		/// <returns></returns>
		public UserAlbum GetById(int id)
		{
			var album = this.UserAlbumRepository.GetById(id);

			if (album == null)
			{
				return album;
			}

			Determine(album);

			return album;
		}

		/// <summary>
		/// Gets all user albums by specification.
		/// </summary>
		/// <param name="specification">The specification.</param>
		/// <returns></returns>
		public IPagedList<UserAlbum, UserAlbumSpecification> GetPaged(UserAlbumSpecification specification)
		{
			var identity = IdentityService.Current;

			if (identity != null)
			{
				specification.ContactId = identity.Id;
			}

			return this.UserAlbumRepository.GetPaged(specification);
		}

		/// <summary>
		/// Gets all user albums with a preview photo by specification.
		/// </summary>
		/// <param name="specification">The specification.</param>
		/// <returns></returns>
		public IPagedList<UserAlbum, UserAlbumSpecification> GetPhotos(UserAlbumSpecification specification)
		{
			var identity = IdentityService.Current;

			if (identity != null)
			{
				specification.ContactId = identity.Id;
			}

			return this.UserAlbumRepository.GetPhotos(specification);
		}

		/// <summary>
		/// Creates the user album.
		/// </summary>
		/// <returns></returns>
		public UserAlbum Create()
		{
			var album = new UserAlbum
			{
				Created = DateTime.Now
			};

			album.Updated = album.Created;

			return album;
		}

		/// <summary>
		/// Determines if user can view this specified album.
		/// </summary>
		/// <param name="album">The album.</param>
		public void Determine(UserAlbum album)
		{
			switch (album.Scope)
			{
				case UserAlbumScope.Private:
					{
						var identity = User.Identity;

						if (identity == null)
						{
							album.IsContact = false;
						}
						else
						{
							var count = this.UserContactService.Count(new UserContactSpecification
							{
								UserId = album.UserId,
								ContactId = identity.Id
							});

							album.IsContact = (album.CanView || album.CanViewAny || (count > 0));
						}
					}
					break;
				default:
					{
						album.IsContact = true;
					}
					break;
			}
		}

		/// <summary>
		/// Inserts the specified user album.
		/// </summary>
		/// <param name="album">The album.</param>
		public void Insert(UserAlbum album)
		{
			album.Validate();

			album.Slug = album.Title.Slug();
			album.BodyParsed = album.Body.BBCodeToHtml(true);

			this.UserAlbumRepository.Insert(album);
		}

		/// <summary>
		/// Inserts the specified user album.
		/// </summary>
		/// <param name="album">The album.</param>
		/// <param name="value">The value.</param>
		public void Insert(UserAlbum album, UserAlbumCreate value)
		{
			value.Validate();

			var identity = IdentityService.Current;

			album.UserId = identity.Id;
			album.Title = value.Title;
			album.Body = value.Body;
			album.Scope = value.Scope;

			this.Insert(album);
		}

		/// <summary>
		/// Updates the specified user album.
		/// </summary>
		/// <param name="album">The album.</param>
		public void Update(UserAlbum album)
		{
			album.Validate();

			album.Slug = album.Title.Slug();
			album.BodyParsed = album.Body.BBCodeToHtml(true);

			this.UserAlbumRepository.Update(album);
		}

		/// <summary>
		/// Updates the specified user album.
		/// </summary>
		/// <param name="album">The album.</param>
		/// <param name="value">The value.</param>
		public void Update(UserAlbum album, UserAlbumUpdate value)
		{
			value.Validate();

			album.Title = value.Title;
			album.Body = value.Body;
			album.Scope = value.Scope;

			this.Update(album);
		}

		/// <summary>
		/// Deletes the specified user album.
		/// </summary>
		/// <param name="album">The album.</param>
		public void Delete(UserAlbum album)
		{
			this.UserAlbumRepository.Delete(album);
		}
	}
}